//
//  LocalAuthenticationManager.m
//  GSBlockChain
//
//  Created by guoshikeji_a on 2018/12/7.
//  Copyright © 2018 guoshikeji. All rights reserved.
//

#import "LocalAuthenticationManager.h"

@implementation LocalAuthenticationManager

static LocalAuthenticationManager *_localAuthenticationManager = nil;
+ (instancetype)sharedLocalAuth {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if (!_localAuthenticationManager) {
            _localAuthenticationManager = [[LocalAuthenticationManager alloc] init];
        }
    });
    return _localAuthenticationManager;
}

- (instancetype)init
{
    self = [super init];
    if (self) {
        [self supportsCheckAction];
    }
    return self;
}
/**
 * !@breif 初始化时判断一下是否支持指纹或者面容
 */
- (void)supportsCheckAction {
    LAContext *context = [[LAContext alloc] init];
    //
    NSError *error = nil;
    BOOL canEveluate = [context canEvaluatePolicy:LAPolicyDeviceOwnerAuthentication error:&error];
    //
    _isSupportLocalAuth = canEveluate;
    if (canEveluate) {
        if (@available(iOS 11.0,*)) {//在这之后可以用API访问
            LABiometryType type = context.biometryType;
            switch (type) {
                case LABiometryTypeNone:
                {
                    _biometryType = DDLABiometryTypeNone;
                }
                    break;
                case LABiometryTypeTouchID:
                {
                    _biometryType = DDLABiometryTypeTouchID;
                }
                    break;
                case LABiometryTypeFaceID:
                {
                    _biometryType = DDLABiometryTypeFaceID;
                }
                    break;
                default:
                    break;
            }
        }else {//iOS11之前 就只有大概通过手机判断了哦 借助QMUI框架
            BOOL isNotchedScreen = [QMUIHelper isNotchedScreen];//是不是全面屏幕 faceid
            if (isNotchedScreen) {
                _biometryType = DDLABiometryTypeFaceID;
            }else {
                _biometryType = DDLABiometryTypeTouchID;
            }
        }
        //
        if (self.biometryType==DDLABiometryTypeNone) {
            _isSupportLocalAuth = false;
        }
    }
    [context invalidate];
    context = nil;
}

/**
 * !@brief 开启一次验证
 */
- (void)startLocalAuthenticationFromController:(UIViewController *)fromController complete:(LocalAuthenticationCompleteBlcok)complete {
    LAContext *context = [[LAContext alloc] init];
    context.localizedFallbackTitle = @"";//设置成空字符串则不显示此按钮
    if (@available(iOS 10.0, *)) {
        context.localizedCancelTitle = BCLocalizedKey(@"Cancel");
    } else {
        // Fallback on earlier versions
        context.localizedFallbackTitle = BCLocalizedKey(@"Cancel");
    }
    NSError *error = nil;
    if ([context canEvaluatePolicy:LAPolicyDeviceOwnerAuthentication error:&error]) {
        [context evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics localizedReason:BCLocalizedKey(@"Pressed Home To Recognized") reply:^(BOOL success, NSError * _Nullable error) {
            //
            if (success) {//验证成功
                dispatch_async(dispatch_get_main_queue(), ^{
                    if (complete) {
                        complete(success,nil);
                    }
                });
            }else if(error){
                switch (error.code) {
                    case LAErrorAuthenticationFailed:{//验证失败
                        dispatch_async(dispatch_get_main_queue(), ^{
                            //需要提示用户
                            NSString *domain = BCLocalizedKey(@"Not Recognized");
                            NSError *newError = [NSError errorWithDomain:domain code:error.code userInfo:nil];
                            if (complete) {
                                complete(false,newError);
                            }
                            //
                            [self showErrorknowWithTitle:domain message:nil controller:fromController];
                        });
                        break;
                    }
                    case LAErrorUserCancel:{//被用户手动取消
                        dispatch_async(dispatch_get_main_queue(), ^{
                            //不做处理
                            if (complete) {
                                complete(false,nil);
                            }
                        });
                    }
                        break;
                    case LAErrorUserFallback:{//用户不使用TouchID,选择手动输入密码 也处理成取消
                        dispatch_async(dispatch_get_main_queue(), ^{
                            //不做处理
                            NSError *newError;
                            if (complete) {
                                complete(false,newError);
                            }
                        });
                    }
                        break;
                    case LAErrorSystemCancel:{//被系统取消 (如遇到来电,锁屏,按了Home键等)
                        dispatch_async(dispatch_get_main_queue(), ^{
                            //不做处理
                            NSError *newError;
                            if (complete) {
                                complete(false,newError);
                            }
                        });
                    }
                        break;
                    case LAErrorPasscodeNotSet:{//无法启动,因为用户没有设置密码
                        dispatch_async(dispatch_get_main_queue(), ^{
                            //需要提示用户
                            NSString *domain = BCLocalizedKey(@"Can not use,Don't set password");
                            NSError *newError = [NSError errorWithDomain:domain code:error.code userInfo:nil];
                            if (complete) {
                                complete(false,newError);
                            }
                            //
                            [self showErrorknowWithTitle:domain message:nil controller:fromController];
                        });
                    }
                        break;
                    case LAErrorTouchIDNotEnrolled:{//无法启动,因为用户没有设置TouchID
                        dispatch_async(dispatch_get_main_queue(), ^{
                            //需要提示用户
                            NSString *domain = BCLocalizedKey(@"Can not use,User not set");
                            NSError *newError = [NSError errorWithDomain:domain code:error.code userInfo:nil];
                            if (complete) {
                                complete(false,newError);
                            }
                            //
                            [self showErrorknowWithTitle:domain message:nil controller:fromController];
                        });
                    }
                        break;
                    case LAErrorTouchIDNotAvailable:{//无效 eg:Face ID 权限引起 TouchID没开
                        dispatch_async(dispatch_get_main_queue(), ^{
                            //需要提示用户
                            NSString *domain = BCLocalizedKey(@"Not Available");
                            NSError *newError = [NSError errorWithDomain:domain code:error.code userInfo:nil];
                            if (complete) {
                                complete(false,newError);
                            }
                            //
                            [self showErrorSettingWithTitle:domain message:nil controller:fromController];
                        });
                    }
                        break;
                    case LAErrorTouchIDLockout:{//被锁定(连续多次验证失败,系统需要用户手动输入密码)
                        dispatch_async(dispatch_get_main_queue(), ^{
                            //需要提示用户
                            NSString *domain = BCLocalizedKey(@"Lockout");
                            NSError *newError = [NSError errorWithDomain:domain code:error.code userInfo:nil];
                            if (complete) {
                                complete(false,newError);
                            }
                            //
                            [self showErrorknowWithTitle:domain message:nil controller:fromController];
                        });
                    }
                        break;
                    case LAErrorAppCancel:{//当前软件被挂起并取消了授权 (如App进入了后台等)
                        dispatch_async(dispatch_get_main_queue(), ^{
                           //不做处理
                            NSError *newError;
                            if (complete) {
                                complete(false,newError);
                            }
                        });
                    }
                        break;
                    case LAErrorInvalidContext:{//当前软件被挂起并取消了授权 (LAContext对象无效)
                        dispatch_async(dispatch_get_main_queue(), ^{
                            //不做处理
                            NSError *newError;
                            if (complete) {
                                complete(false,newError);
                            }
                        });
                    }
                        break;
                    default: {//其他未知错误 弹框提示 验证出错
                        dispatch_async(dispatch_get_main_queue(), ^{
                            //需要提示用户
                            NSString *domain = BCLocalizedKey(@"Unknown Error");
                            NSError *newError = [NSError errorWithDomain:domain code:error.code userInfo:nil];
                            if (complete) {
                                complete(false,newError);
                            }
                            //
                            [self showErrorknowWithTitle:domain message:nil controller:fromController];
                        });
                    }
                        break;
                }
            }
        }];
    }else {
        /**
         如果不支持 不会进入启动界面 出现提示用户 验证出现bug
         */
        //需要提示用户
        NSString *domain = BCLocalizedKey(@"Not supports");
        NSError *newError = [NSError errorWithDomain:domain code:error.code userInfo:nil];
        if (complete) {
            complete(false,newError);
        }
        //
        [self showErrorknowWithTitle:domain message:nil controller:fromController];
    }
}


/**
 显示底部按钮为“知道了”
 */
- (void)showErrorknowWithTitle:(NSString *)title message:(NSString *)message controller:(UIViewController *)controller {
    if (!controller) {
        return;
    }
    UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
    UIAlertAction *knowAction = [UIAlertAction actionWithTitle:BCLocalizedKey(@"I know") style:UIAlertActionStyleDefault handler:nil];
    [alertVC addAction:knowAction];
    [controller presentViewController:alertVC animated:true completion:false];
}
/**
 显示底部按钮为“取消”
 */
- (void)showErrorCancelWithTitle:(NSString *)title message:(NSString *)message controller:(UIViewController *)controller {
    if (!controller) {
        return;
    }
    UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:BCLocalizedKey(@"Cancel") style:UIAlertActionStyleCancel handler:nil];
    [alertVC addAction:cancelAction];
    [controller presentViewController:alertVC animated:true completion:false];
}
/**
 显示底部按钮为“取消”和“设置” 权限不足时
 */
- (void)showErrorSettingWithTitle:(NSString *)title message:(NSString *)message controller:(UIViewController *)controller {
    if (!controller) {
        return;
    }
    UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
    UIAlertAction *settingAction = [UIAlertAction actionWithTitle:BCLocalizedKey(@"Setting") style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        
    }];
    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:BCLocalizedKey(@"Cancel") style:UIAlertActionStyleCancel handler:nil];
    [alertVC addAction:settingAction];
    [alertVC addAction:cancelAction];
    [controller presentViewController:alertVC animated:true completion:false];
}


@end
